package com.eduagent.xwqeduagent.service.lmpl;

import cn.hutool.core.util.ObjectUtil;
import com.eduagent.xwqeduagent.adviser.MyLoggerAdvisor;
import com.eduagent.xwqeduagent.app.agent.LectureAnalysis;
import com.eduagent.xwqeduagent.app.teacher.MultimodalGeneration.MultiModGeneration;
import com.eduagent.xwqeduagent.constant.prompt.generateQuiz;
import com.eduagent.xwqeduagent.exception.BusinessException;
import com.eduagent.xwqeduagent.exception.ErrorCode;
import com.eduagent.xwqeduagent.exception.ThrowUtils;
import com.eduagent.xwqeduagent.model.entity.CourseOutline;
import com.eduagent.xwqeduagent.model.vo.LectureAnalysisResultVO;
import com.eduagent.xwqeduagent.model.vo.QuizQuestion;
import com.eduagent.xwqeduagent.model.vo.QuizQuestionSet;
import com.eduagent.xwqeduagent.service.TeacherService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Slf4j
@Service
@RequiredArgsConstructor
public class TeacherServicelmpl implements TeacherService {

    private final MultiModGeneration multiModGeneration;

    @Resource
    private LectureAnalysis lectureAnalysis;

    @Resource
    private ChatClient chatClient;

    @Resource
    private Advisor loveAppRagCloudAdvisor;

    @Resource
    private ToolCallback[] allTools;

    @Resource
    private ObjectMapper objectMapper;

    /**
     * 教学大纲生成
     * @param classname 课程名称
     * @param sessionId 对话id
     * @return
     */
    @Override
    public CourseOutline generateClassOutline(String classname, String sessionId) {
        ThrowUtils.throwIf(ObjectUtil.isEmpty(classname)||ObjectUtil.isEmpty(sessionId), ErrorCode.NOT_FOUND_ERROR,"课程名称和对话id不能为空");
        return multiModGeneration.GenerateClassOutline(classname, sessionId);
    }

    /**
     * 生成习题集
     * @param teachingContent 教学内容（可选）
     * @param numQuestions 题目数量
     * @param desiredQuestionTypes 期望的题目类型
     * @param contentFile 上传的文件（可选）
     * @return 习题集对象
     */
    @Override
    public QuizQuestionSet generateQuizQuestions(
            String teachingContent,
            Integer numQuestions,
            List<String> desiredQuestionTypes,
            MultipartFile contentFile) {

        log.info("开始生成习题，内容长度：{}，题目数量：{}，文件：{}",
                teachingContent != null ? teachingContent.length() : 0,
                numQuestions,
                contentFile != null ? contentFile.getOriginalFilename() : "无文件");

        // 验证参数 - 至少需要提供内容或文件之一
        ThrowUtils.throwIf(ObjectUtil.isEmpty(teachingContent) && (contentFile == null || contentFile.isEmpty()),
                ErrorCode.PARAMS_ERROR, "请提供教学内容或上传内容文件");

        try {
            // 保存原始教学内容的副本
            String workingContent = teachingContent;

            // 如果有文件，进行讲义分析
            if (contentFile != null && !contentFile.isEmpty()) {
                try {
                    // 使用随机生成的会话ID
                    String sessionId = "quiz_" + System.currentTimeMillis();
                    String userId = "system_quiz_generator";

                    log.info("先进行讲义分析...");
                    LectureAnalysisResultVO analysisResult = lectureAnalysis.lectureAnalysis(
                            workingContent,
                            userId,
                            sessionId,
                            contentFile
                    );

                    // 处理分析结果
                    if (analysisResult != null && "success".equals(analysisResult.getStatus())) {
                        String analysisContent = analysisResult.getAnalysisContent();

                        log.info("讲义分析成功，分析内容长度: {}",
                                analysisContent != null ? analysisContent.length() : 0);

                        // 合并分析结果到教学内容
                        if (!ObjectUtil.isEmpty(workingContent)) {
                            workingContent = workingContent + "\n\n讲义分析结果：\n" + analysisContent;
                        } else {
                            workingContent = "讲义内容分析结果：\n" + analysisContent;
                        }
                    } else {
                        log.warn("讲义分析未成功，状态：{}，将继续使用原始教学内容",
                                analysisResult != null ? analysisResult.getStatus() : "null");
                    }
                } catch (Exception e) {
                    log.error("讲义分析失败", e);
                }
            }

            // 构建完整提示词
            StringBuilder fullPrompt = new StringBuilder(workingContent);
            if (numQuestions != null && numQuestions > 0) {
                fullPrompt.append("\n\n请帮我生成 ").append(numQuestions).append(" 道题目。");
            }

            if (desiredQuestionTypes != null && !desiredQuestionTypes.isEmpty()) {
                String typesString = desiredQuestionTypes.stream()
                        .map(String::trim)
                        .filter(type -> !type.isEmpty())
                        .collect(Collectors.joining(", "));

                if (!typesString.isEmpty()) {
                    fullPrompt.append("\n题目类型请主要侧重于以下几种: ").append(typesString).append("。");
                    fullPrompt.append(" 同时，也欢迎结合内容适当生成一些其他相关类型的题目以保证多样性，除非题目数量要求较少。");
                } else {
                    fullPrompt.append("\n请生成多样化的题目类型。");
                }
            } else {
                fullPrompt.append("\n请生成多样化的题目类型。");
            }

            fullPrompt.append("\n请严格按照预定义的JSON格式输出所有题目。");

            log.info("开始生成习题，提示词长度: {}", fullPrompt.length());

            // 收集生成的内容
            StringBuilder contentCollector = new StringBuilder();

            // 调用大模型进行流式生成并收集
            Flux<String> contentFlux = chatClient
                    .prompt()
                    .system(generateQuiz.generateQuiz_PROMPT)
                    .user(fullPrompt.toString())
                    .advisors(new MyLoggerAdvisor())

                    .tools(allTools)
                    .stream()
                    .content();

            // 收集所有内容
            String fullContent = contentFlux.collectList()
                    .map(chunks -> {
                        for (String chunk : chunks) {
                            contentCollector.append(chunk);
                        }
                        return contentCollector.toString();
                    })
                    .block(Duration.ofMinutes(3)); // 设置最长等待时间为3分钟

            // 提取JSON内容
            String jsonContent = extractJsonContent(fullContent);

            // 解析为习题集对象
            QuizQuestionSet quizQuestionSet = parseQuizJson(jsonContent);

            log.info("习题生成完成，习题数量: {}",
                    quizQuestionSet != null && quizQuestionSet.getQuestions() != null ?
                            quizQuestionSet.getQuestions().size() : 0);

            return quizQuestionSet;

        } catch (Exception e) {
            log.error("生成习题失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成习题失败: " + e.getMessage());
        }
    }

    /**
     * 从大模型返回的内容中提取JSON
     */
    private String extractJsonContent(String content) {
        // 检查是否有JSON代码块标记
        if (content.contains("```json")) {
            Pattern pattern = Pattern.compile("```json\\s*\\n?(.*?)\\n?```", Pattern.DOTALL);
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                return matcher.group(1).trim();
            }
        }

        // 检查是否有普通代码块标记
        if (content.contains("```")) {
            Pattern pattern = Pattern.compile("```\\s*\\n?(.*?)\\n?```", Pattern.DOTALL);
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                return matcher.group(1).trim();
            }
        }

        // 尝试直接提取JSON数组
        if (content.contains("[") && content.contains("]")) {
            Pattern pattern = Pattern.compile("\\[\\s*\\{.*\\}\\s*\\]", Pattern.DOTALL);
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                return matcher.group(0).trim();
            }
        }

        // 没有代码块标记，直接返回原内容
        return content.trim();
    }

    /**
     * 解析习题JSON为QuizQuestionSet对象
     */
    private QuizQuestionSet parseQuizJson(String jsonContent) {
        try {
            // 解析JSON节点
            JsonNode jsonNode = objectMapper.readTree(jsonContent);

            // 如果是数组，表示只有题目列表
            if (jsonNode.isArray()) {
                // 解析为题目列表
                List<QuizQuestion> questions = objectMapper.readValue(jsonContent,
                        new TypeReference<List<QuizQuestion>>() {});

                // 创建习题集合
                return QuizQuestionSet.builder()
                        .questions(questions)
                        .build();
            }
            // 如果是对象，可能已经是QuizQuestionSet格式
            else if (jsonNode.isObject() && jsonNode.has("questions")) {
                return objectMapper.readValue(jsonContent, QuizQuestionSet.class);
            }
            // 其他格式，尝试强制解析
            else {
                log.warn("习题JSON格式不符合预期，尝试强制解析");

                // 直接解析JSON字符串到对象
                QuizQuestionSet quizQuestionSet = objectMapper.readValue(jsonContent, QuizQuestionSet.class);

                if (quizQuestionSet == null || quizQuestionSet.getQuestions() == null || quizQuestionSet.getQuestions().isEmpty()) {
                    log.error("解析习题JSON失败，无法提取有效题目");
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR, "无法解析习题内容");
                }

                return quizQuestionSet;
            }
        } catch (Exception e) {
            log.error("解析习题JSON失败", e);

            // 创建一个包含错误信息的题目
            QuizQuestion errorQuestion = QuizQuestion.builder()
                    .questionText("习题生成出错，请重试")
                    .type("ERROR")
                    .explanation("解析生成的内容时出错: " + e.getMessage())
                    .build();

            List<QuizQuestion> errorList = Collections.singletonList(errorQuestion);

            return QuizQuestionSet.builder()
                    .questions(errorList)
                    .build();
        }
    }

}
